iT邦幫忙

2023 iThome 鐵人賽

DAY 8
0
export const textInputOf =
  ({ minLen, maxLen }: { minLen: number; maxLen: number }) =>
  (input: string) =>
    pipe(
      input,
      validateMinLen(minLen),
      Either.flatMap(validateMaxLen(maxLen)),
      Either.flatMap(validateWhiteList),
      // 以下兩行先忽略
      // Either.mapRight(ofValid),
      // Either.merge 
    )

回顧昨天的驗證程式,如果用 if else 寫會是這樣

const textInputOf = ({ minLen, maxLen }: { minLen: number; maxLen: number }) =>
(input: string): InvalidTextInput | ValidTextInput => {

	const either1 = validateMinLen(minLen)(input)
	
	if(either1._tag==='Right'){
		const input2 = either1.right
		const either2 = validateMaxLen(maxLen)(input2)
		if(either2._tag==='Right'){
			const input3 = either2.right
			const either3 = validateMaxLen(maxLen)(input3)
			if(either2._tag==='Right'){
				return either3
			}else{
				return either2
			}
		}else{
			return either2
		}
	}else{
		return either1
	}
}

mapRight, flatten, and flatMap

其中導致程式變成巢狀,而且一直重複出現的邏輯就是 Either flatMap
它由 mapRightflatten 組成

Either mapRight
想像 Either 是一個型別盒子,裡面可能有是 Right 也可能是 Left
如果盒子裡面是 Right 就把右值取出放入一個能產生任意型別的 callback function,再把這個 function 的回傳值 Output2 包裝進 Either
如果盒子裡面是 Left 就回傳 Either
https://ithelp.ithome.com.tw/upload/images/20230923/201586156MSwEj3W0f.png

有時候剛好 callback function 的輸出也是一個 Either 盒子

https://ithelp.ithome.com.tw/upload/images/20230923/2015861550pvKbbzx8.png

這時候就要再加上一個 flatten 的操作

Either flatten
把重複兩層的其中一層盒子拆掉,保留值在同一層盒子裡
https://ithelp.ithome.com.tw/upload/images/20230923/20158615JcEhSm3WPb.png

mapRightflatten 串起來就會變成這樣

https://ithelp.ithome.com.tw/upload/images/20230923/201586158AKAlg2bti.png

再把中間轉換的部份省略就得到了 flatMap

Effect flatMap
mapRight + flatten
https://ithelp.ithome.com.tw/upload/images/20230923/20158615piuVJOtp27.png

merge

Either 盒子中,Output 被包在 Right 裡面, Error 被包在 Left 裡面
當我們不需要區分 LeftRight 了,我們就可以把兩邊結果合併起來

https://ithelp.ithome.com.tw/upload/images/20230923/20158615RrbwI9lemQ.png

textInputOf 為例,經過 mapRight 處理後 Either 的左右值分別是 InvalidTextInputValidTextInput。這兩個型別都有 tag,可以合併成一個 sum type ,且合併後的 sum type 也是有意義的,因此我們就可以把 Either 盒子拆掉,把最終結果 InvalidTextInput | ValidTextInput 合在一起拿出來。

https://ithelp.ithome.com.tw/upload/images/20230923/20158615LHOFuSgXLW.png

把滑鼠移上去看型別在是一種相當好用的 debug 技巧
對型別有疑問? 滑鼠移上去就對了 !


最後要強調的是,Either 只是其中一種資料盒子,還有很多種盒子也有 mapflatMap 等概念。這些操作具體會做甚麼跟盒子類型有關。如果你想對資料型別盒子有更多瞭解,推薦參考 hanna 大大的文章


上一篇
D07 - 軌道導向設計
下一篇
D09 - 開始元件測試
系列文
從 Next.js 開始的 Functional Programming30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言